package com.gupao.webmvc.maping;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gupao.webmvc.annotion.GPAutoWrite;
import com.gupao.webmvc.annotion.GPCollector;
import com.gupao.webmvc.annotion.GPRequestMapping;
import com.gupao.webmvc.annotion.GPServerce;



public class GPDispatherServlet extends HttpServlet{

	private Properties contextConfig=new Properties();
	
	private List<String> classNames=new ArrayList<String>();
	
	private Map<String,Object> ioc=new HashMap<String,Object>();
	
	private Map<String,Method> handerMapping=new HashMap<String,Method>();
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//6、调用自己的dispather方法
		try {
			doDispathder(req,resp);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			resp.getWriter().write(e.getStackTrace().toString());
			
		}
	}

	@Override
	public void init(ServletConfig config) throws ServletException
	{
		System.out.println("init...");
		
		//1、加载配置文件
		doLoadConfig(config.getInitParameter("contextConigLocation"));
		
		//2、扫描到所有相关的类
		doScanner(contextConfig.getProperty("scanPackage"));
		//3、初始化刚刚扫描到的类并初始化到容器中
		doInstance();
		//4、自动注入
		doAutoWrited();
		//初始化handMapping
		initHandMapping();
		System.out.println("gp spring mvc is init ok");
		
	}

	//将url和实例对象进行关联
	private void initHandMapping() {
		// TODO Auto-generated method stub
		if(ioc.isEmpty()){
			return;
		}
		
		for(Map.Entry<String, Object> entry:ioc.entrySet()){
			
			Class<?> clazz=entry.getValue().getClass();
			
			if(!clazz.isAnnotationPresent(GPCollector.class)){
				continue;
			}
			String baseurl="";
			if(clazz.isAnnotationPresent(GPRequestMapping.class)){
				
				GPRequestMapping requestMaping=clazz.getAnnotation(GPRequestMapping.class);
				baseurl=requestMaping.value();
			}
			
			//spring只认public的方法
			Method[] methods=clazz.getMethods();
			for (Method method : methods) {
				
				if(!method.isAnnotationPresent(GPRequestMapping.class)){
					continue;
				}
				GPRequestMapping requestMaping=method.getAnnotation(GPRequestMapping.class);
				String url=(baseurl+"/"+requestMaping.value()).replaceAll("/+", "/");
				handerMapping.put(url, method);
				System.out.println("Mapped: "+url+","+method);
			}
		}
		
	}

	//依赖注入
	private void doAutoWrited() {
		// TODO Auto-generated method stub
		if(ioc.isEmpty()){
			return;
		}
		for(Map.Entry<String, Object> entry:ioc.entrySet()){
			//注入：就是给属性赋值
		Field[] fields=	entry.getValue().getClass().getDeclaredFields();
			
			for (Field field : fields) {
				
				if(!field.isAnnotationPresent(GPAutoWrite.class)){
					continue;
				}
				GPAutoWrite autowrite=field.getAnnotation(GPAutoWrite.class);
				String beanName=autowrite.value();
				if("".equals(beanName.trim())){
					beanName=field.getType().getName();
				}
				field.setAccessible(true);
				try {
					field.set(entry.getValue(), ioc.get(beanName));
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					continue;
				}
			}
		}
		
		
	}

	//ioc容器初始化
	private void doInstance() {
		// TODO Auto-generated method stub
	 if(classNames.isEmpty()){
		 return;
	 }
	 try {
		for(String className:classNames){
		Class<?> clazz=	 Class.forName(className);
		//利用反射机制将类制造出来
		if(clazz.isAnnotationPresent(GPCollector.class)){
			Object instance=clazz.newInstance();
			//类名的首字母小写
		String bean=	lowerFirstCase(clazz.getSimpleName());
			
		ioc.put(bean, instance);		
		
		}else if(clazz.isAnnotationPresent(GPServerce.class)){
			//1、默认的首字母小写
			//2如果是自定义的，我们会优先使用自定义的
			
			GPServerce service=	clazz.getAnnotation(GPServerce.class);
			String beanName=service.value();
			if("".equals(beanName.trim())){
				beanName=lowerFirstCase(clazz.getSimpleName());
			}
			
			Object instance=clazz.getInterfaces();
			ioc.put(beanName, instance);
			//3如果写的是接口，自动注入他的实现类
			
			Class<?>[] interfaces= clazz.getInterfaces();
			for (Class<?> i : interfaces) {
				ioc.put(i.getName(), instance);
			}			
			
		}else {
			//直接忽略
			continue;
		}
		 }
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	 
	}

	private String lowerFirstCase(String simpleName) {
		// TODO Auto-generated method stub
		char[] chars=simpleName.toCharArray();
		chars[0]+=32;
		return String.valueOf(chars);
	}

	//扫描所有相关类
	private void doScanner(String scanPackage) {
		// TODO Auto-generated method stub
	URL url=this.getClass().getClassLoader().getResource("/"+scanPackage.replaceAll("\\.", "/"));
	
	File classPathDir=new File(url.getFile());
		for(File file:classPathDir.listFiles()){
			if(file.isDirectory()){
				doScanner(scanPackage+"."+file.getName());
			}else{
				
				String className=scanPackage+"."+file.getName().replace(".class", ""); 
				classNames.add(className);
			}
			
		}
	}

	//获取配置参数
	private void doLoadConfig(String contextConigLocation) {
		// TODO Auto-generated method stub
		System.out.print(contextConigLocation);

	InputStream is=	this.getClass().getClassLoader().getResourceAsStream(contextConigLocation);
	try {
		contextConfig.load(is);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}finally {
		if(null !=is){
			try {
				is.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	
	}

	//接收前段传过来的url并处理
	private void doDispathder(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		// TODO Auto-generated method stub
		//url绝对路径替换成相对路径
		String url= req.getRequestURI();
		String contextPath=req.getContextPath();
		url=url.replace(contextPath, "").replaceAll("/+", "/");
		
		if(!handerMapping.containsKey(url)){
			
			resp.getWriter().write("404 NOt found");
			return;
		}
		Method method=this.handerMapping.get(url);

		//获取方法的参数列表


		System.out.println(method);
	}
	
	
}
